import config from '@/config'
import { AbstractModel, AbstractModelConstructor } from '@/model/model'
import { default as positionManager, type Scatter } from '@/service/position'

export default abstract class AbstractCanvas<T extends AbstractModel> {
    /**
     * 存储画布中的内容对象
     */
    public models: T[] = []

    /**
     * 画布宽度
     */
    public width: number = config.canvas.width

    /**
     * 画布高度
     */
    public height: number = config.canvas.height

    /**
     * 构造函数
     */
    public constructor(
        protected app = document.querySelector<HTMLDivElement>('#app')!,
        protected canvas = document.createElement('canvas'),
        public ctx = canvas.getContext('2d')!
    ) {
        this.createCanvas()
    }

    /**
     * 创建画布。宽高从配置文件中读取。
     */
    protected createCanvas() {
        const { width, height } = config.canvas
        this.setCanvasId()
        this.canvas.width = width
        this.canvas.height = height
        // this.app.insertAdjacentElement('afterbegin', this.canvas)
        this.app.appendChild(this.canvas)
    }

    protected clearCanvas() {
        // console.log('clear')
        this.ctx.clearRect(0, 0, this.width, this.height)
    }

    /**
     * 在画布中创建模型实例
     */
    protected createModels(count: number, model: AbstractModelConstructor<T>, scatter?: Scatter, allowOverlap = false) {
        const positions = positionManager.positionBatch(count, scatter, allowOverlap)
        positions.forEach((p) => this.models.push(new model(this.ctx, p)))
    }

    /**
     * 在画布中渲染模型实例
     */
    protected renderModels() {
        this.models.forEach((d) => d.draw())
    }

    // ============== abstract methods ==============

    /**
     * render() 函数。供外部调用
     */
    public abstract render(): void

    /**
     * 设置 canvas 的 id。格式：canvas-*
     */
    protected abstract setCanvasId(): void
}
